<script lang="ts">
    import {ParamsInterface} from "@/uni_modules/u-popup/components/u-popup/types";
    import props from "./props";
    import mixin from "@/uni_modules/u-tools/mixin/mixin";
    import mpMixin from "@/uni_modules/u-tools/mixin/mpMixin";
    import UPopup from "@/uni_modules/u-popup/components/u-popup/u-popup.vue";
    import UScroller from "@/uni_modules/u-scroller/components/u-scroller/u-scroller.vue";

    export default defineComponent({
        // 类名
        name: "u-dialog",
        // 组件
        components: {UPopup, UScroller},
        // 混合
        mixins: [props, mixin, mpMixin],
        // 事件
        emits: ["beforeOpen", "open", "beforeClose", "close"],
        // 暴露方法
        expose: ["open", "close"],
        // 数据
        data()
        {
            return {
                showDialog: false, // 显示弹窗
                showTrans: false, // 是否显示过渡
                transparent: null, // 透传的数据
                dialogWidth: "", // 弹窗宽度
                dialogHeight: "", // 弹窗高度
                popup: {
                    mode: "center",
                    duration: 300,
                    zIndex: 10000,
                    round: 10,
                    backgroundColor: "#fff",
                    spacing: 10,
                    safeAreaInsetBottom: true,
                    safeAreaInsetTop: false,
                    safeCapsule: false
                } as Record<string, any>
            };
        },
        // 监听器
        watch: {
            // 显示状态监听
            show(status: boolean): void
            {
                if (status)
                {
                    this.open();
                }
                else
                {
                    this.close();
                }
            }
        },
        // 计算函数
        computed: {},
        // 方法
        methods: {
            // 打开
            open(params?: ParamsInterface)
            {
                // 判断是否显示，如果是，则不执行
                if (this.showDialog)
                {
                    return;
                }

                // 弹窗宽度
                this.dialogWidth = this.width !== "auto" ? isNumber(this.width) ? this.$u.unit(this.width) : this.width.includes("%") ? this.width : this.$u.unit(this.width) : "auto";

                // 弹窗高度
                this.dialogHeight = this.height !== "auto" ? isNumber(this.height) ? this.$u.unit(this.height) : this.height.includes("%") ? this.height : this.$u.unit(this.height) : "auto";

                // 当前弹窗显示的方式
                this.popup.mode = this.$attrs.mode || "center";

                // 当前弹窗显示时长
                this.popup.duration = this.$attrs.duration || 300;

                // 当前弹窗显示层级
                this.popup.zIndex = this.$attrs.zIndex || 10000;

                // 当前弹窗显示的圆角
                this.popup.round = this.$attrs.round || 10;

                // 当前弹窗显示的背景色
                this.popup.backgroundColor = this.$attrs.backgroundColor || "#fff";

                // 当前弹窗显示的间距
                this.popup.spacing = this.$attrs.spacing || 10;

                // 当前是否为iPhoneX留出底部安全距离
                this.popup.safeAreaInsetBottom = this.$attrs.safeAreaInsetBottom != null ? this.$attrs.safeAreaInsetBottom : true;

                // 当前是否留出顶部安全距离（状态栏高度）
                this.popup.safeAreaInsetTop = this.$attrs.safeAreaInsetTop != null ? this.$attrs.safeAreaInsetTop : true;

                // 当前是否留出顶部胶囊安全距离（顶部胶囊栏高度）
                this.popup.safeCapsule = this.$attrs.safeCapsule != null ? this.$attrs.safeCapsule : true;

                // 弹出层参数
                if (params)
                {
                    // 当前弹窗显示的方式
                    if (params.mode && ["center", "top", "bottom", "left", "right"].includes(params.mode))
                    {
                        this.popup.mode = params.mode;
                    }

                    // 显示时长
                    if (params.duration)
                    {
                        this.popup.duration = params.duration;
                    }

                    // 层级
                    if (params.zIndex)
                    {
                        this.popup.zIndex = params.zIndex;
                    }

                    // 圆角
                    if (params.round)
                    {
                        this.popup.round = this.$u.unit(params.round);
                    }

                    // 背景色
                    if (params.backgroundColor)
                    {
                        this.popup.backgroundColor = params.backgroundColor;
                    }

                    // 内容间距
                    if (params.spacing)
                    {
                        this.popup.spacing = this.$u.unit(params.spacing);
                    }

                    // 是否为iPhoneX留出底部安全距离
                    if (params.safeAreaInsetBottom != null)
                    {
                        this.popup.safeAreaInsetBottom = params.safeAreaInsetBottom;
                    }

                    // 是否留出顶部安全距离（状态栏高度）
                    if (params.safeAreaInsetTop != null)
                    {
                        this.popup.safeAreaInsetTop = params.safeAreaInsetTop;
                    }

                    // 是否留出顶部胶囊安全距离（顶部胶囊栏高度）
                    if (params.safeCapsule != null)
                    {
                        this.popup.safeCapsule = params.safeCapsule;
                    }
                }

                // 透传的数据
                this.transparent = params && params.data ? params.data : null;

                // 当前视口区域宽度
                const screenWidth = uni.getSystemInfoSync().windowWidth;

                // 当前视口区域高度
                const screenHeight = uni.getSystemInfoSync().windowHeight;

                // 当前需要预留的安全距离
                const safeAreaInsetsHeight: number[] = [];

                // 如果是顶部安全距离，则需要留出顶部安全距离
                if (this.popup.safeAreaInsetTop)
                {
                    safeAreaInsetsHeight.push(this.$u.getStatusBarHeight());
                }

                // 如果是底部安全距离，则需要留出底部安全距离
                if (this.popup.safeAreaInsetBottom)
                {
                    safeAreaInsetsHeight.push(this.$u.getSafeAreaInsets());
                }

                // 如果是顶部胶囊安全距离，则需要留出顶部胶囊安全距离
                if (this.popup.safeCapsule)
                {
                    safeAreaInsetsHeight.push(this.$u.getCapsuleGeometry().height);
                }

                // 显示弹窗
                this.showDialog = true;

                // 动态计算宽度
                if (this.dialogWidth === "auto")
                {
                    // 如果是左侧、右侧以及居中滑出，则宽度为屏幕宽度的80%
                    if (["left", "right", "center"].includes(this.popup.mode))
                    {
                        this.dialogWidth = this.$u.unit(screenWidth * 0.8);
                    }
                }
                // 如果是顶部以及底部滑出，就算设置了宽度，也会以屏幕宽度为准
                else if (["top", "bottom"].includes(this.popup.mode))
                {
                    this.dialogWidth = this.$u.unit(screenWidth - 20);
                }

                // 动态计算高度
                if (this.dialogHeight === "auto")
                {
                    // 如果是顶部、底部以及居中滑出，则高度为屏幕高度的80%
                    if (["top", "bottom", "center"].includes(this.popup.mode))
                    {
                        this.dialogHeight = this.$u.unit(screenHeight * 0.8);
                    }
                    // 如果是左侧以及右侧滑出（这样才能正常出现滚动条）
                    else if (["left", "right"].includes(this.popup.mode))
                    {
                        this.dialogHeight = this.$u.unit(screenHeight - 20 - safeAreaInsetsHeight.reduce((next: number, current: number) => next + current, 0));
                    }
                }
                // 左侧滑出以及右侧滑出，就算设置了高度，也会以屏幕高度为准
                else if (["left", "right"].includes(this.popup.mode))
                {
                    this.dialogHeight = this.$u.unit(screenHeight - 20 - safeAreaInsetsHeight.reduce((next: number, current: number) => next + current, 0));
                }

                // 延时执行，以便过渡动画顺利执行
                nextTick(() =>
                {
                    // 显示过渡
                    this.showTrans = true;
                });
            },
            // 关闭
            close()
            {
                // 隐藏过渡
                this.showTrans = false;

                // 延时执行，以便过渡动画顺利执行
                nextTick(() =>
                {
                    // 隐藏弹窗
                    this.showDialog = false;
                });
            },
            // 打开前事件
            beforeOpenHandler(fn: Function): void
            {
                this.$emit("beforeOpen", fn);
            },
            // 打开后事件
            openHandler(): void
            {
                this.$emit("open");
            },
            // 关闭前事件
            beforeCloseHandler(): void
            {
                this.$emit("beforeClose");
            },
            // 关闭后事件
            closeHandler(): void
            {
                // 隐藏过渡
                this.showTrans = false;

                // 延时执行，以便过渡动画顺利执行
                nextTick(() =>
                {
                    // 隐藏弹窗
                    this.showDialog = false;

                    this.$emit("close");
                });
            }
        }
    });
</script>

<template>
    <!-- 弹窗组件 -->
    <view
        v-if="showDialog"
        :class="[customClass]"
        class="u-dialog"
    >
        <u-popup
            :show="showTrans"
            v-bind="popup"
            @close="closeHandler"
            @open="openHandler"
            @before-open="beforeOpenHandler"
            @before-close="beforeCloseHandler"
        >
            <!-- 自定义插槽 -->
            <view
                :style="{width: dialogWidth, maxHeight: dialogHeight}"
                class="custom-popup-slots"
            >
                <!-- 标题 -->
                <view
                    v-if="title"
                    class="title"
                >
                    <u-text
                        :font-size="titleSize"
                        :font-weight="titleWeight"
                        :justify-content="titleAlign"
                        :text="title"
                    />
                </view>
                <!-- //标题 -->

                <!-- 滚动区域 -->
                <view class="control">
                    <u-scroller
                        :enable-refresh="false"
                        :spacing="0"
                    >
                        <!-- 使用模板数据，其实就是作用域插槽 -->
                        <template v-if="useTemplateData">
                            <slot :data="transparent" />
                        </template>
                        <!-- //使用模板数据，其实就是作用域插槽 -->

                        <!-- 默认插槽 -->
                        <template v-else>
                            <slot />
                        </template>
                        <!-- //默认插槽 -->
                    </u-scroller>
                </view>
                <!-- //滚动区域 -->

                <!-- 按钮区域 -->
                <view class="button-group">
                    <u-button
                        text="取消"
                        type="error"
                        :plain="true"
                    />
                    <u-button
                        text="确定"
                        type="primary"
                    />
                </view>
                <!-- //按钮区域 -->
            </view>
            <!-- //自定义插槽 -->
        </u-popup>
    </view>
    <!-- //弹窗组件 -->
</template>

<style lang="scss" scoped>
    .custom-popup-slots
    {
        height: 100%;
        display: grid;
        grid-auto-rows: auto 1fr auto;

        // 标题
        .title
        {
            padding: 10px 0;
        }

        // 内容区
        .control
        {
            min-height: 0;
        }

        // 按钮区域
        .button-group
        {
            display: flex;
            align-items: center;
            justify-content: space-around;
            margin-top: 10px;
        }
    }
</style>